#pragma once

#include<memory>

#include <string>
#include"backendshen/eigen_types.h"


namespace myslam{
namespace backend{
class Vertex;
class Edge{
public:
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
    explicit Edge(int residual_dimension, 
                  int num_verticies, 
                  const std::vector<std::string> &verticies_types = std::vector<std::string>());
    virtual ~Edge();
    unsigned long Id() const { return id_; }
    //设置一个顶点
    bool AddVertex(std::shared_ptr<Vertex> vertex)
    {
        verticies_.emplace_back(vertex);
        return true;
    }
    //设置一些顶点
    bool SetVertex(std::vector<std::shared_ptr<Vertex>>& vertices)
    {
        verticies_ = vertices;
        return true;
    }
    //返回第i个顶点
    std::shared_ptr<Vertex>  GetVertex(int i)
    {
        return verticies_[i];
    }
    //返回所有顶点
    std::vector<std::shared_ptr<Vertex>> Verticies() const
    {
        return verticies_;
    }
    //返回关联的顶点数
    size_t NumVertices() const { return verticies_.size(); }
    //返回边的类型信息，在子类中实现
    virtual std::string TypeInfo() const = 0;
    virtual void ComputeResidual() =0;  //计算残差由子类实现
    //计算雅可比，由子类实现
    virtual void ComputeJacobians() = 0;
    //计算平方误差，会乘以信息矩阵
    double Chi2();

    //返回残差
    VecX Residual() const {
        return residual_;
    }
    //返回雅可比
    std::vector<MatXX> Jacobians() const { return jacobins_; }
    //设置信息矩阵
    void SetInformation(const MatXX &information)
    {
        information_ = information;
    }
    //返回信息矩阵
    MatXX Information() const 
    {
        return information_;
    }
    //设置观测信息
    void SetObservation(const VecX& observation)
    {
        observation_ = observation;
    }
    //检查边的信息是否全部设置
    bool CheckValid();
    int OrderingId() const { return ordering_id_; }
    void SetOrderingId(int id) { ordering_id_ = id; }

protected : 
    unsigned long id_;
    int ordering_id_;
    std::vector<std::string> verticies_types_;       // 各个顶点的类型
    std::vector<std::shared_ptr<Vertex>> verticies_; // 该边对应的顶点
    VecX residual_;                                  // 残差
    std::vector<MatXX> jacobins_;                    // 雅可比   每个雅可比维度是residual x vertex[i]
    MatXX information_;                              // 信息矩阵
    VecX observation_;                               // 观测信息
};
}
}



